package io.le.starter.lock.locker;

import io.etcd.jetcd.ByteSequence;
import io.etcd.jetcd.Client;
import io.etcd.jetcd.Lease;
import io.etcd.jetcd.Lock;
import io.etcd.jetcd.lease.LeaseGrantResponse;
import io.etcd.jetcd.lease.LeaseKeepAliveResponse;
import io.etcd.jetcd.lock.LockResponse;
import io.grpc.stub.StreamObserver;

import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.Condition;

/**
 * createTime：2025-04-03 13:58
 * description：etcd lock
 */
public class EtcdLock extends AbstractLock {


    public Client etcdClint;

    public static final long DEFAULT_TIME = 20L;

    public Long leaseId;

    public String lockPath;

    public EtcdLock(Client etcdClint, String lockName) {
        this.etcdClint = etcdClint;
        this.lockName = lockName;
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public Condition newCondition() {
        return null;
    }

    @Override
    public void lock() {
        //创建租约
        createLease();
        //创建锁
        createLock();
    }

    private void createLease() {
        Lease leaseClient = etcdClint.getLeaseClient();
        try {
            LeaseGrantResponse leaseGrantResponse = leaseClient.grant(DEFAULT_TIME).get();
            leaseId = leaseGrantResponse.getID();
            StreamObserver<LeaseKeepAliveResponse> observer = new StreamObserver() {
                @Override
                public void onNext(Object o) {

                }

                @Override
                public void onError(Throwable throwable) {

                }

                @Override
                public void onCompleted() {

                }
            };


            //租约自动续期
            leaseClient.keepAlive(leaseId, observer);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    public void createLock() {
        Lock lockClient = etcdClint.getLockClient();
        CompletableFuture<LockResponse> lockResponse = lockClient.lock(ByteSequence.from(this.lockName, StandardCharsets.UTF_8), leaseId);
        try {
            this.lockPath = lockResponse.get().getKey().toString();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void unlock() {
        //释放锁
        if (Objects.nonNull(this.lockPath)) {
            try {
                etcdClint.getLockClient().unlock(ByteSequence.from(this.lockPath, StandardCharsets.UTF_8)).get();
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException("un lock fail " + this.lockPath);
            }
        }
        //释放租约
        if (Objects.nonNull(this.leaseId)) {
            //revoke释放租约
            try {
                etcdClint.getLeaseClient().revoke(this.leaseId).get();
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException("revoke fail " + this.leaseId);
            }

        }
    }
}
